#include "DXGraphics.h"

DXGraphics* gDGraphics = 0 ;

DXGraphics::DXGraphics()
{
	center = D3DXVECTOR3(0.0f, 0.0f, 0) ;
	count = 0 ;
}

DXGraphics::~DXGraphics( )
{
	// clean up DirectX and COM
	cleanD3D( ) ;
}

LPDIRECT3DTEXTURE9 DXGraphics::loadSprite( char * filename )
{
	//loads a sprite to the next empty slot
	D3DXCreateTextureFromFileExA(d3ddev,    // the device pointer
                                (LPCSTR)filename,    // the sprite name
                                D3DX_DEFAULT_NONPOW2,    // default width
                                D3DX_DEFAULT_NONPOW2,    // default height
                                D3DX_DEFAULT,    // no mip mapping
                                NULL,    // regular usage
                                D3DFMT_A8R8G8B8,    // 32-bit pixels with alpha
                                D3DPOOL_MANAGED,    // typical memory handling
                                D3DX_DEFAULT,    // no filtering
                                D3DX_DEFAULT,    // no mip filtering
                                D3DCOLOR_XRGB(255, 0, 255),    // the hot-pink color key
                                NULL,    // no image info struct
                                NULL,    // not using 256 colors
                                &m_sprArr[count]);    // load to sprite

	//increments the count and returns the sprite
	count++ ;
	return m_sprArr[count-1];
}

// this function initializes and prepares Direct3D for use
void DXGraphics::initD3D(HWND hWnd)
{
    d3d = Direct3DCreate9(D3D_SDK_VERSION);    // create the Direct3D interface

	D3DPRESENT_PARAMETERS d3dpp;    // create a struct to hold various device information

    ZeroMemory(&d3dpp, sizeof(d3dpp));    // clear out the struct for use
    d3dpp.Windowed = TRUE;    // program windowed, not fullscreen
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;    // discard old frames
	d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;    // set the back buffer format to 32-bit
    d3dpp.BackBufferWidth = SCREEN_WIDTH;    // set the width of the buffer
    d3dpp.BackBufferHeight = SCREEN_HEIGHT;    // set the height of the buffer

    // create a device class using this information and the info from the d3dpp stuct
    d3d->CreateDevice(D3DADAPTER_DEFAULT,
                      D3DDEVTYPE_HAL,
                      hWnd,
                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                      &d3dpp,
                      &d3ddev);

	m_hWnd = hWnd ;

	//hide windows cursor
	ShowCursor( NULL ) ;
	d3ddev->ShowCursor(false) ;

	D3DXCreateSprite(d3ddev, &d3dspt);    // create the Direct3D Sprite object

	D3DXCreateFont(d3ddev,    // the D3D Device
                   20,    // font height
                   0,    // default font width
                   FW_BOLD,    // font weight
                   1,    // not using MipLevels
                   false,    // italic font
                   DEFAULT_CHARSET,    // default character set
                   OUT_DEFAULT_PRECIS,    // default OutputPrecision,
                   DEFAULT_QUALITY,    // default Quality
                   DEFAULT_PITCH | FF_DONTCARE,    // default pitch and family
                   L"Arial",    // use Facename Arial
                   &d3dfnt_game);    // the font object

	D3DXCreateFont(d3ddev,    // the D3D Device
                   30,    // font height
                   0,    // default font width
                   FW_BOLD,    // font weight
                   1,    // not using MipLevels
                   false,    // italic font
                   DEFAULT_CHARSET,    // default character set
                   OUT_DEFAULT_PRECIS,    // default OutputPrecision,
                   DEFAULT_QUALITY,    // default Quality
                   DEFAULT_PITCH | FF_DONTCARE,    // default pitch and family
                   L"Arial",    // use Facename Arial
                   &d3dfnt_menu);    // the font object

	return ;
}

void DXGraphics::Update()
{
	//Updates game cursor's position
	GetCursorPos(&mousePos) ; //gets window cursor position on monitor screen
	ScreenToClient( m_hWnd, &mousePos ) ; //maps the location of the cursor onto the client window
}

void DXGraphics::createBox( int a_width, int a_height, int a_offset )
{
	// create the textbox
	GetWindowRect(m_hWnd, &textbox);
	textbox.right = a_width + a_offset ;
	textbox.bottom = SCREEN_HEIGHT ;
	textbox.left = a_offset ;
	textbox.top = a_height ;
}

LPCSTR DXGraphics::getCharBuffer( int a_mines, int a_flags )
{
	//print the string into the char buffer
	sprintf_s( buffer, "Flags/Mines: %i / %i", a_flags, a_mines ) ;

	return buffer ;
}

// this is the function used to render a single frame
void DXGraphics::render_frame( Map * a_map, int state )
{
    // clear the window to WHITE
    d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255, 255, 255), 1.0f, 0);

    d3ddev->BeginScene();    // begins the 3D scene

    d3dspt->Begin(D3DXSPRITE_ALPHABLEND);    // begin sprite drawing with transparent background

	//********drawing stuff*************//
	if( state == PLAY )
	{
		//drawing the map
		for( int col = 0; col < a_map->getWidth(); ++col )
			for( int row = 0; row < a_map->getHeight(); ++row )
			{
				D3DXMatrixTranslation( &spriteTranslation, (float)col * SPRITE_SIZE + a_map->getOffset(), (float)row * SPRITE_SIZE, 0 );	// move sprite from center
				d3dspt->SetTransform( &spriteTranslation ) ;
				int mapID = a_map->getID( col, row ) ;
				d3dspt->Draw( m_sprArr[mapID], NULL, &center, NULL, D3DCOLOR_XRGB( 255, 255, 255 ) );	// draw the sprite
			}

		//draw text
		d3dfnt_game->DrawTextA(NULL, getCharBuffer( a_map->getMines(), a_map->getFlags() ), -1, &textbox, DT_TOP | DT_LEFT | DT_NOCLIP, D3DCOLOR_ARGB(255, 0, 0, 0));
		d3dfnt_game->DrawTextA(NULL, "Restart - R\n Quit - Q", -1, &textbox, DT_TOP | DT_RIGHT | DT_NOCLIP, D3DCOLOR_ARGB(255, 0, 0, 0));
	}
	else if( state == MAIN )
	{
		//draw main menu text
		d3dfnt_menu->DrawTextA(NULL, 
			"MINESWEEPER\n by: David Fairweather\n\n"
			"Choose a difficulty to play:\n\n"
			"1 - EASY     2 - NORMAL     3 - HARD\n\n"
			"Or press Esc to Exit the game\n\n"
			"Left-click to reveal a tile\n\n"
			"Right-click to flag/unflag a tile\n\n"
			"Flagged tiles cannot be revealed\n\n"
			"Reveal all tiles while avoiding the mines to WIN", 
			-1, 
			&textbox, 
			DT_CENTER | DT_NOCLIP, 
			D3DCOLOR_ARGB(255, 0, 0, 0));
	}
	else
	{
		//draw WIN menu text
		d3dfnt_menu->DrawTextA(NULL, 
			"YOU WIN!!!\n\n"
			"Press Esc to exit the game\n\n"
			"Or choose a difficulty to play again:\n\n"
			"1 - EASY     2 - NORMAL     3 - HARD\n\n", 
			-1, 
			&textbox, 
			DT_CENTER | DT_NOCLIP, 
			D3DCOLOR_ARGB(255, 0, 0, 0));
	}
	
	//draw the cursor
	D3DXMatrixTranslation( &spriteTranslation, mousePos.x, mousePos.y, 0 );	// move sprite from center
	d3dspt->SetTransform( &spriteTranslation ) ;
	d3dspt->Draw( m_sprArr[MAX_SPRITES-1], NULL, &center, NULL, D3DCOLOR_XRGB( 255, 255, 255 ) );	// draw the sprite

	d3dspt->End();    // end sprite drawing

    d3ddev->EndScene();    // ends the 3D scene

    d3ddev->Present(NULL, NULL, NULL, NULL);   // displays the created frame on the screen
}

// cleans up Direct3D and COM
void DXGraphics::cleanD3D(void)
{
	d3dfnt_game->Release() ;
	d3dfnt_menu->Release() ;
    d3ddev->Release();
    d3d->Release();
	d3dspt->Release() ;
    return;
}